package tp.pr5;

import tp.pr5.items.CodeCard;

/**
 * A street links two places A and B. All streets are two-way streets. If a street is defined as Street(A,NORTH,B) this means that Place B is at NORTH of Place A and Place A is at south of Place B
 * 
 */
public class Street 
{
	
	private Place source;
	private Direction direction;
	private Place target;
	private boolean isOpen;
	private String code;


	/**
	 * Constructor.
	 * @param source - Source place 
	 * @param direction - Represents how is placed the target place with respect to the source place.
	 * @param target - Target place 
	 */
	
	public Street(Place source, Direction direction, Place target)
	{
		this.source	= source;
		this.direction = direction;
		this.target	= target;
		this.isOpen = true;
	}
	
	/**
	 * Constructor.
	 * @param source - Source place 
	 * @param direction - Represents how is placed the target place with respect to the source place.
	 * @param target - Target place 
	 * @param isOpen - Determines is the street is opened or closed
	 * @param code - The code that opens and closes the street
	 */
	
	public Street(Place source, Direction direction, Place target, boolean isOpen, String code)
	{
		this.source	= source;
		this.direction = direction;
		this.target	= target;
		this.isOpen = isOpen;
		this.code = code;
	}
	
	/**
	 * Checks if the street comes out from a place in a given direction
	 * 
	 * @param place - The place to check 
	 * @param whichDirection - Direction used.
	 * 
	 * @return Returns true if the street comes out from the input Place.
	 */
	
	public boolean comeOutFrom(Place place, Direction whichDirection)
	{		
		return (this.source.equals(place) && this.direction.equals(whichDirection)) || (this.target.equals(place) && this.direction.equals(whichDirection.opposite()));
	}

	/**
	 * Returns the place of the other side from the place whereAmI.
	 * @param whereAmI - The place where I am.
	 * 
	 * @return It returns the Place at the other side of the street. Returns null if whereAmI does not belong to the street.
	 */
	
	public Place nextPlace(Place whereAmI)
	{
		if(this.source.equals(whereAmI))
		{
			return this.target;
		} 
		else if(this.target.equals(whereAmI))
		{
			return this.source;
		} 
		else 
		{
			return null;
		}
	}
	
	/**
	 * Checks if the street is open or closed
	 * 
	 * @return true, if the street is open, and false when the street is closed
	 */
	
	public boolean isOpen()
	{
		return this.isOpen;	
	}
	
	/**
	 * Tries to open a street using a code card. Codes must match in order to complete this action
	 * 
	 * @return true if the action has been completed
	 */
	
	public boolean open(CodeCard card)
	{
		if(this.code.equals(card.getCode()))
		{
			this.isOpen = true;
			return true;
		}
		return false;
	}
	
	/**
	 * Tries to close a street using a code card. Codes must match in order to complete this action
	 * 
	 * @return true if the action has been completed
	 */
	
	public boolean close(CodeCard card)
	{
		if(this.code.equals(card.getCode()))
		{
			this.isOpen = false;
			return true;
		}
		else return false;
	}
	
	/**
	 * Gets the source from the place
	 * 
	 * @return A Place that represents the source
	 */
	
	public Place getSource()
	{
		return this.source;
	}
	
	/**
	 * Gets the target from the place
	 * 
	 * @return A Place that represents the target
	 */
	
	public Place getTarget()
	{
		return this.target;
	}
	
	/**
	 * Gets the direction from the place
	 * 
	 * @return A Direction that represents the direction
	 */
	
	public Direction getDirection()
	{
		return this.direction;
	}
	
	/**
	 * Gets the code of the door from the place
	 * 
	 * @return A String that represents the code
	 */
	
	public String getCode() 
	{
		return this.code;
	}
	
	
}
